//
//  KLPeerSrceen.m
//  kularkDemo
//
//  Created by szblsx2 on 2020/4/16.
//  Copyright © 2020 szblsx. All rights reserved.
//

#import "KLPeerSrceen.h"
#import "KLClient.h"

@interface KLPeerSrceen ()<RTCPeerConnectionDelegate>
//视频源
@property (nonatomic, strong) RTCVideoSource *screenVideoSource;
//视频track
@property (nonatomic, strong) RTCVideoTrack *screenVideoTrack;
//本地连接对象
@property (nonatomic, strong) RTCPeerConnection *mScreenPeerConnection;
//媒体采集器
@property (nonatomic, strong) RTCVideoCapturer *mVideoCapturer;
//工厂对象(上行传入)
@property (nonatomic, weak) RTCPeerConnectionFactory *mPeerConnectionFactory;
//信令对象(上行传入)
@property (nonatomic, weak) KLClient *mKLClient;
//ice服务器地址(上行传入)
@property (nonatomic, weak) NSArray <RTCIceServer *> *iceServers;
//ice收集状态 yes代表收集完成
@property (nonatomic, assign) BOOL bSendSdp;
//ice地址集合
@property (nonatomic, strong) NSMutableArray *mIceCandidates;

@end

@implementation KLPeerSrceen

/**初始化KLPeerSrceen*/
- (instancetype)initWithClient:(KLClient *)client
                       factory:(RTCPeerConnectionFactory *)factory
                    iceServers:(NSArray<RTCIceServer *> *)iceServers
{
    if (self = [super init]) {
        _mKLClient = client;
        _mPeerConnectionFactory = factory;
        _iceServers = iceServers;
        _roomId = @"";
        _streamId = @"";
    }
    return self;
}

/**创建PeerConnection*/
- (void)initPeerConnection
{
    if (!_mScreenPeerConnection) {
        RTCConfiguration *configuration = [[RTCConfiguration alloc] init];
        configuration.iceServers = self.iceServers;
        configuration.disableIPV6 = YES;
        configuration.activeResetSrtpParams = YES;
        configuration.sdpSemantics = RTCSdpSemanticsUnifiedPlan;
        configuration.bundlePolicy = RTCBundlePolicyMaxBundle;
        configuration.tcpCandidatePolicy = RTCTcpCandidatePolicyDisabled;
        self.mScreenPeerConnection = [self.mPeerConnectionFactory peerConnectionWithConfiguration:configuration constraints:[self defaultConstraint] delegate:self];
        //添加视频track
        [self.mScreenPeerConnection addTrack:self.screenVideoTrack streamIds:@[@"ARDAMS"]];
        
        [self createOffer];
    }
}

/**删除PeerConnection*/
- (void)freePeerConnection
{
    _bSendSdp = NO;
    [_mIceCandidates removeAllObjects];
    
    if (_screenVideoTrack) {
        _screenVideoTrack = nil;
    }
    if (_mScreenPeerConnection) {
        [_mScreenPeerConnection close];
        _mScreenPeerConnection = nil;
    }
}

/**创建offer SDP*/
- (void)createOffer
{
    if (!_mScreenPeerConnection) {
        return;
    }
    [_mScreenPeerConnection offerForConstraints:[self defaultConstraint] completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
        if (error) {
            NSLog(@"creatOffer error : %@",error);
            return;
        }
        __weak __typeof(self) ws = self;
        [self->_mScreenPeerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
            if (error) {
                NSLog(@"ScreenPeer setLocal error : %@",error);
                return;
            }
            //发送publish到信令服务器
            ws.bSendSdp = YES;
            [ws.mKLClient sendPublish:ws.roomId sdp:ws.mScreenPeerConnection.localDescription.sdp bScreen:YES];
        }];
    }];
}

/**接收到远端answer SDP处理*/
- (void)onRemoteDescription:(RTCSessionDescription *)sessionDescription
{
    [self.mScreenPeerConnection setRemoteDescription:sessionDescription completionHandler:^(NSError * _Nullable error) {
        if (error) {
            NSLog(@"ScreenPeer setRemoteDescription error %@",error);
        }else{
            NSLog(@"ScreenPeer setRemoteDescription success");
        }
    }];
}

/** 发送自定义视频数据*/
- (void)sendVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer
{
    
    NSLog(@"录屏上传中..");
    
    if (!_mVideoCapturer) {
        _mVideoCapturer = [[RTCVideoCapturer alloc] initWithDelegate:self.screenVideoSource];
    }
    if (!_screenVideoTrack) {
        _screenVideoTrack = [self.mPeerConnectionFactory videoTrackWithSource:self.screenVideoSource trackId:VIDEO_TRACK_ID];
        _screenVideoTrack.isEnabled = YES;
    }
    
    if (CMSampleBufferGetNumSamples(sampleBuffer) != 1 || !CMSampleBufferIsValid(sampleBuffer) ||
        !CMSampleBufferDataIsReady(sampleBuffer)) {
        return;
    }
    
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    if (pixelBuffer == nil) {
        return;
    }
    RTCCVPixelBuffer *rtcPixelBuffer = [[RTCCVPixelBuffer alloc] initWithPixelBuffer:pixelBuffer];
    int64_t timeStampNs =
    CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) * NSEC_PER_SEC;
    RTCVideoFrame *videoFrame = [[RTCVideoFrame alloc] initWithBuffer:rtcPixelBuffer
                                                             rotation:RTCVideoRotation_0
                                                          timeStampNs:timeStampNs];
    [_mVideoCapturer.delegate capturer:_mVideoCapturer didCaptureVideoFrame:videoFrame];
    
    [self initPeerConnection];
}

#pragma mark - RTCPeerConnectionDelegate

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeSignalingState:(RTCSignalingState)stateChanged
{
    NSLog(@"");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didAddStream:(RTCMediaStream *)stream
{
    NSLog(@"");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveStream:(RTCMediaStream *)stream
{
    NSLog(@"");
}

- (void)peerConnectionShouldNegotiate:(RTCPeerConnection *)peerConnection
{
    NSLog(@"");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceConnectionState:(RTCIceConnectionState)newState
{
    NSLog(@"");
}

/**ICEcandidate收集状态变化*/
- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeIceGatheringState:(RTCIceGatheringState)newState
{
    if (newState == RTCIceGatheringStateComplete && _bSendSdp) {
        NSLog(@"IceCandidate收集完成");
        for (RTCIceCandidate *candidate in self.mIceCandidates) {
            [self sendLocalIceCandidate:candidate];
        }
    }
}

/**获取到新的ICEcandidate*/
- (void)peerConnection:(RTCPeerConnection *)peerConnection didGenerateIceCandidate:(RTCIceCandidate *)candidate
{
    NSLog(@"IceCandidate收集 : %@",candidate.sdp);
    [self.mIceCandidates addObject:candidate];
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didRemoveIceCandidates:(NSArray<RTCIceCandidate *> *)candidates
{
    NSLog(@"");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didOpenDataChannel:(RTCDataChannel *)dataChannel
{
    NSLog(@"");
}

- (void)peerConnection:(RTCPeerConnection *)peerConnection didChangeConnectionState:(RTCPeerConnectionState)newState
{
    NSLog(@"");
}

#pragma mark - Private Method

/**媒体描述约束*/
- (RTCMediaConstraints *)defaultConstraint
{
    NSDictionary *mandatory = @{kRTCMediaConstraintsOfferToReceiveAudio : kRTCMediaConstraintsValueTrue,
                                kRTCMediaConstraintsOfferToReceiveVideo : kRTCMediaConstraintsValueTrue};
    RTCMediaConstraints *constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatory optionalConstraints:nil];
    return constraints;
}

/**发送ICE给信令服务器*/
- (void)sendLocalIceCandidate:(RTCIceCandidate *)candidate
{
    NSDictionary *dic = @{@"type":@"candidate",@"label":@(candidate.sdpMLineIndex),@"id":candidate.sdpMid,@"candidate":candidate.sdp};
    [self.mKLClient sendIceCandidate:self.roomId mid: self.streamId object:dic bPub:true];
}

#pragma mark - Getter

- (NSMutableArray *)mIceCandidates
{
    if (!_mIceCandidates) {
        _mIceCandidates = [NSMutableArray array];
    }
    return _mIceCandidates;
}

- (RTCVideoSource *)screenVideoSource
{
    if (!_screenVideoSource) {
        _screenVideoSource = [self.mPeerConnectionFactory videoSource];
    }
    return _screenVideoSource;
}

@end
